package labs.fourth;

import java.util.Arrays;
import java.util.List;

import labs.utilities.MyList;

public class SyntaxParser extends StaticErrorReport {
	public static MyList tokens;

	public static boolean parseExact(MyList tokens, String str) {
		if (tokens.peek().getValue().equals(str)) {
			tokens.nextToken();
			return true;
		} else {
			setErrorMessage(tokens.peek());
			return false;
		}
	}

	public static boolean parseIdentifier(MyList tokens) {
		if (tokens.peek().isIdentifier()) {
			tokens.nextToken();
			return true;
		} else {
			setErrorMessage(tokens.peek());
			return false;
		}
	}

	public static boolean parseQualifiedIdentifier(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		while (tokens.peek().getValue().equals(".")) {
			tokens.nextToken();
			if (!parseIdentifier(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		return true;
	}

	public static boolean parseQualifiedIdentifierList(MyList tokens) {
		if (!parseQualifiedIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		while (tokens.peek().getValue().equals(",")) {
			tokens.nextToken();
			if (!parseQualifiedIdentifier(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		return true;
	}

	public static boolean parseCompilationUnit(MyList tokens) {
		parseAnnotations(tokens);
		if (parseExact(tokens, "package")) {
			if (!parseQualifiedIdentifier(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens, ";")) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		MyList tokens1 = tokens.createBranch();
		while (parseImportDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}
		if (!parseTypeDeclaration(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseImportDeclaration(MyList tokens) {
		if (!tokens.peek().getValue().equals("import")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		if (tokens.peek().getValue().equals("")) {
			tokens.nextToken();
		}
		if (!parseQualifiedIdentifier(tokens)) {
			if (!tokens.peek().getValue().equals("*")) {
				setErrorMessage(tokens.peek());
				return false;
			} else {
				tokens.nextToken();
			}
		}
		if (!tokens.peek().getValue().equals(";")) {
			setErrorMessage(tokens.peek());
			return false;
		}

		return true;

	}

	public static boolean parseTypeDeclaration(MyList tokens) {

		return parseClassOrInterfaceDeclaration(tokens);
	}

	public static boolean parseClassOrInterfaceDeclaration(MyList tokens) {
		parseModifier(tokens);
		// if (!parseModifier(tokens)) {
		// setErrorMessage(tokens.peek());
		// return false;
		// }
		MyList tokens1 = tokens.createBranch();
		MyList tokens2 = tokens.createBranch();
		if (parseClassDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
		} else if (parseInterfaceDeclaration(tokens2)) {
			tokens.mergeBranch(tokens2);
		} else {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseClassDeclaration(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		MyList tokens2 = tokens.createBranch();
		if (parseNormalClassDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
		} else if (parseEnumDeclaration(tokens2)) {
			tokens.mergeBranch(tokens2);
		} else {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseInterfaceDeclaration(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		MyList tokens2 = tokens.createBranch();
		if (parseNormalInterfaceDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
		} else if (parseAnnotationTypeDeclaration(tokens2)) {
			tokens.mergeBranch(tokens2);
		} else {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseNormalClassDeclaration(MyList tokens) {
		if (!parseExact(tokens, "class")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		// boolean typeParameters = false;
		// boolean extendsType = false;
		// boolean implementsTypeList = false;

		MyList tokens1 = tokens.createBranch();
		if (parseTypeParameters(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		MyList tokens2 = tokens.createBranch();
		if (tokens2.peek().getValue().equals("extends")) {
			tokens2.nextToken();
			if (parseType(tokens2)) {
				tokens.mergeBranch(tokens2);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		MyList tokens3 = tokens.createBranch();
		if (tokens3.peek().getValue().equals("implements")) {
			tokens3.nextToken();
			if (parseTypeList(tokens3)) {
				tokens.mergeBranch(tokens3);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
		}

		if (!parseClassBody(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseEnumDeclaration(MyList tokens) {
		if (!tokens.peek().getValue().equals("enum")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (tokens1.peek().getValue().equals("implements")) {
			tokens1.nextToken();
			if (parseTypeList(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		if (!parseEnumBody(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseNormalInterfaceDeclaration(MyList tokens) {
		if (!tokens.peek().getValue().equals("interface")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseTypeParameters(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		MyList tokens2 = tokens.createBranch();
		if (tokens2.peek().getValue().equals("extends")) {
			tokens2.nextToken();
			if (parseType(tokens2)) {
				tokens.mergeBranch(tokens2);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		MyList tokens3 = tokens.createBranch();
		if (tokens3.peek().getValue().equals("implements")) {
			tokens3.nextToken();
			if (parseTypeList(tokens3)) {
				tokens.mergeBranch(tokens3);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
		}

		if (!parseInterfaceBody(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}

		return true;
	}

	public static boolean parseAnnotationTypeDeclaration(MyList tokens) {
		if (!tokens.peek().getValue().equals("@")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		if (!tokens.peek().getValue().equals("interface")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseAnnotationTypeBody(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseType(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseBasicType(tokens1)) {
			tokens.mergeBranch(tokens1);
			while (tokens.peek().getValue().equals("[]")) {
				tokens.nextToken();
			}
			return true;
		}
		MyList tokens2 = tokens.createBranch();
		if (parseReferenceType(tokens2)) {
			tokens.mergeBranch(tokens2);
			while (tokens.peek().getValue().equals("[]")) {
				tokens.nextToken();
			}
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseReferenceType(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseTypeArguments(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		while (tokens.peek().getValue().equals(".")) {
			tokens.nextToken();
			if (!parseIdentifier(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens1 = tokens.createBranch();
			if (parseTypeArguments(tokens1)) {
				tokens.mergeBranch(tokens1);
			}
		}
		return true;
	}

	public static boolean parseTypeArguments(MyList tokens) {
		if (!tokens.peek().getValue().equals("<")) {
			setErrorMessage(tokens.peek());
			return false;
		}

		do {
			tokens.nextToken();
			if (!parseTypeArgument(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (tokens.peek().getValue().equals(","));

		if (!tokens.peek().getValue().equals(">")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseTypeArgument(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseReferenceType(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		if (!tokens.peek().getValue().equals("?")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		if (tokens.peek().getValue().equals("extends")
				|| tokens.peek().getValue().equals("super")) {
			tokens.nextToken();
			if (!parseReferenceType(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		return true;
	}

	public static boolean parseNonWildcardTypeArguments(MyList tokens) {
		if (!tokens.peek().getValue().equals("<")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		if (!parseTypeList(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!tokens.peek().getValue().equals(">")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseTypeList(MyList tokens) {
		do {
			if (!parseReferenceType(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseTypeArgumentsOrDiamond(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "<") && parseExact(tokens1, ">")) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		return parseTypeArguments(tokens);
	}

	public static boolean parseNonWildcardTypeArgumentsOrDiamond(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "<") && parseExact(tokens1, ">")) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		return parseNonWildcardTypeArguments(tokens);
	}

	public static boolean parseTypeParameters(MyList tokens) {
		if (!parseExact(tokens, "<")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		do {
			if (!parseTypeParameter(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));

		return parseExact(tokens, ">");
	}

	public static boolean parseTypeParameter(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (parseExact(tokens, "extends") && !parseBound(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseBound(MyList tokens) {
		do {
			if (!parseReferenceType(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, "&"));
		return true;
	}

	public static boolean parseAnnotations(MyList tokens) {
		if (!parseAnnotation(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		while (parseAnnotation(tokens1)) {
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}
		return true;
	}

	public static boolean parseAnnotation(MyList tokens) {
		if (!parseExact(tokens, "@")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseQualifiedIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}

		if (parseExact(tokens, "(")) {
			MyList tokens1 = tokens.createBranch();
			if (parseAnnotationElement(tokens1)) {
				tokens.mergeBranch(tokens1);
			}
			if (!parseExact(tokens, ")")) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		return true;
	}

	public static boolean parseAnnotationElement(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		MyList tokens2 = tokens.createBranch();
		if (parseElementValuePairs(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		if (parseElementValue(tokens2)) {
			tokens.mergeBranch(tokens2);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseElementValuePairs(MyList tokens) {
		do {
			if (!parseElementValuePair(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseElementValuePair(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, "=")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseElementValue(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseElementValue(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		MyList tokens2 = tokens.createBranch();
		MyList tokens3 = tokens.createBranch();
		if (parseAnnotation(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		if (parseExpression1(tokens2)) {
			tokens.mergeBranch(tokens2);
			return true;
		}
		if (parseElementValueArrayInitializer(tokens3)) {
			tokens.mergeBranch(tokens3);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseElementValueArrayInitializer(MyList tokens) {
		if (!parseExact(tokens, "{")) {
			setErrorMessage(tokens.peek());
			return false;
		}

		MyList tokens1 = tokens.createBranch();
		if (parseElementValue(tokens1)) {
			tokens.mergeBranch(tokens1);
		}

		parseExact(tokens, ",");

		if (!parseExact(tokens1, "}")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseElementValues(MyList tokens) {
		do {
			if (!parseElementValue(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseClassBody(MyList tokens) {
		if (!parseExact(tokens, "{")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		while (parseClassBodyDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}

		if (!parseExact(tokens, "}")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseClassBodyDeclaration(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		while (parseModifier(tokens1)) {
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}
		if (parseMemberDecl(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		parseExact(tokens, "static");
		if (parseBlock(tokens)) {
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseMemberDecl(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseMethodOrFieldDecl(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "void")) {
			if (!parseIdentifier(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseVoidMethodDeclaratorRest(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseIdentifier(tokens1)) {
			if (!parseConstructorDeclaratorRest(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseGenericMethodOrConstructorDecl(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseClassDeclaration(tokens1)) {

			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseInterfaceDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseMethodOrFieldDecl(MyList tokens) {
		if (!parseType(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseMethodOrFieldRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseMethodOrFieldRest(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseFieldDeclaratorsRest(tokens1)) {
			if (parseExact(tokens1, ";")) {
				tokens.mergeBranch(tokens1);
				return true;
			}
		}

		if (parseMethodDeclaratorRest(tokens)) {
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseFieldDeclaratorsRest(MyList tokens) {
		do {
			if (!parseVariableDeclaratorRest(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseMethodDeclaratorRest(MyList tokens) {
		if (!parseFormalParameters(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		while (parseExact(tokens, "[]")) {

		}
		if (parseExact(tokens, "throws")) {
			if (!parseQualifiedIdentifierList(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		if (parseExact(tokens, ";")) {
			return true;
		}
		return parseBlock(tokens);
	}

	/**
	 * FormalParameters [throws QualifiedIdentifierList] (Block | ;)
	 **/
	public static boolean parseVoidMethodDeclaratorRest(MyList tokens) {
		if (!parseFormalParameters(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (parseExact(tokens, "throws")) {
			if (!parseQualifiedIdentifierList(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		if (parseExact(tokens, ";")) {
			return true;
		}
		return parseBlock(tokens);
	}

	/**
	 * FormalParameters [throws QualifiedIdentifierList] Block
	 * 
	 * @param tokens
	 * @return
	 */
	public static boolean parseConstructorDeclaratorRest(MyList tokens) {
		if (!parseFormalParameters(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (parseExact(tokens, "throws")) {
			if (!parseQualifiedIdentifierList(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		return parseBlock(tokens);
	}

	/**
	 * TypeParameters GenericMethodOrConstructorRest
	 * 
	 * @param tokens
	 * @return
	 */
	public static boolean parseGenericMethodOrConstructorDecl(MyList tokens) {
		if (!parseTypeParameters(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseGenericMethodOrConstructorDecl(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	/**
	 * (Type | void) Identifier MethodDeclaratorRest Identifier
	 * ConstructorDeclaratorRest
	 * 
	 * @param tokens
	 * @return
	 */
	public static boolean parseGenericMethodOrConstructorRest(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "void") || parseType(tokens1)) {
			tokens.mergeBranch(tokens1);
			if (!parseIdentifier(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseMethodDeclaratorRest(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			return true;
		}

		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseConstructorDeclaratorRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseInterfaceBody(MyList tokens) {
		if (!parseExact(tokens, "{")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseInterfaceBody(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, "}")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseInterfaceBodyDeclaration(MyList tokens) {
		if (parseExact(tokens, ";")) {
			return true;
		}
		return true;
	}

	public static boolean parseInterfaceMemberDecl(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseInterfaceMethodOrFieldDecl(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "void")) {
			if (!parseIdentifier(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseVoidInterfaceMethodDeclaratorRest(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseInterfaceGenericMethodDecl(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseClassDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseInterfaceDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseInterfaceMethodOrFieldDecl(MyList tokens) {
		if (!parseType(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseInterfaceMethodOrFieldRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseInterfaceMethodOrFieldRest(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseConstantDeclaratorsRest(tokens1)) {
			if (!parseExact(tokens1, ";")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseInterfaceMethodDeclaratorRest(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseConstantDeclaratorsRest(MyList tokens) {
		do {
			if (!parseConstantDeclaratorRest(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseConstantDeclaratorRest(MyList tokens) {
		while (parseExact(tokens, "[]")) {

		}
		if (!parseExact(tokens, "=")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseVariableInitializer(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseConstantDeclarator(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseConstantDeclaratorRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseInterfaceMethodDeclaratorRest(MyList tokens) {
		if (!parseFormalParameters(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		while (parseExact(tokens, "[]")) {

		}
		if (parseExact(tokens, "throws")) {
			if (!parseQualifiedIdentifierList(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		if (!parseExact(tokens, ";")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseVoidInterfaceMethodDeclaratorRest(MyList tokens) {
		if (!parseFormalParameters(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (parseExact(tokens, "throws")) {
			if (!parseQualifiedIdentifierList(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		if (!parseExact(tokens, ";")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseInterfaceGenericMethodDecl(MyList tokens) {
		if (!parseTypeParameters(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseType(tokens1)) {
			tokens.mergeBranch(tokens1);
		} else if (!parseExact(tokens, "void")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseInterfaceMethodDeclaratorRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseFormalParameters(MyList tokens) {
		if (!parseExact(tokens, "(")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseFormalParameterDecls(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		if (!parseExact(tokens, ")")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseFormalParameterDecls(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		while (parseVariableModifier(tokens1)) {
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}
		if (!parseType(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseFormalParameterDeclsRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseVariableModifier(MyList tokens) {
		if (parseExact(tokens, "final")) {
			return true;
		} else if (parseAnnotation(tokens)) {
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseFormalParameterDeclsRest(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseVariableDeclaratorId(tokens1)) {
			while (parseExact(tokens1, ",")) {
				if (!parseFormalParameterDecls(tokens1)) {
					setErrorMessage(tokens.peek());
					return false;
				}
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		if (parseExact(tokens, "...")) {
			if (parseVariableDeclaratorId(tokens)) {
				return true;
			}
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseVariableDeclaratorId(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		while (parseExact(tokens, "[]")) {
		}
		return true;
	}

	public static boolean parseVariableDeclarators(MyList tokens) {
		do {
			if (!parseVariableDeclarator(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseVariableDeclarator(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseVariableDeclaratorRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseVariableDeclaratorRest(MyList tokens) {
		while (parseExact(tokens, "[]")) {
//			System.out.println("SyntaxParser.parseVariableDeclaratorRest()");
		}
		if (parseExact(tokens, "=")) {
			if (!parseVariableInitializer(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		return true;
	}

	public static boolean parseVariableInitializer(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseArrayInitializer(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		if (parseExpression(tokens)) {
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseArrayInitializer(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
//		if(parseExact(tokens1, "new")) {
//			if(!parseType(tokens1)){
//				return false;
//			}
//			tokens.mergeBranch(tokens1);
//		}
		if (!parseExact(tokens, "{")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		do {
			tokens1 = tokens.createBranch();
			if (!parseVariableInitializer(tokens1)) {
				break;
			}
			tokens.mergeBranch(tokens1);
		} while (parseExact(tokens, ","));

		if (!parseExact(tokens, "}")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseBlock(MyList tokens) {
		if (!parseExact(tokens, "{")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseBlockStatements(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, "}")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseBlockStatements(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		while (parseBlockStatement(tokens1)) {
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}
		return true;
	}

	public static boolean parseBlockStatement(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseLocalVariableDeclarationStatement(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseClassOrInterfaceDeclaration(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseStatement(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseLocalVariableDeclarationStatement(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		while (parseVariableModifier(tokens1)) {
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}
		if (!parseType(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
//		System.out.println(tokens.peek());
//		if (tokens.peek().getValue().equals("Z4359")) {
//			System.out.println("Z4359");
//		}
		if (!parseVariableDeclarators(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, ";")) {
			return false;
		}
		return true;
	}

	public static boolean parseStatement(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseBlock(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}

		if (parseExact(tokens1, ";")) {
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseIdentifier(tokens1)) {
			if (parseExact(tokens1, ":")) {
				tokens.mergeBranch(tokens1);
				return true;
			}
		}

		tokens1 = tokens.createBranch();
		if (parseStatementExpression(tokens1)) {
			if (parseExact(tokens1, ";")) {
				tokens.mergeBranch(tokens1);
				return true;
			}
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "if")) {
			if (!parseParExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseStatement(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (parseExact(tokens1, "else")) {
				if (!parseStatement(tokens1)) {
					setErrorMessage(tokens.peek());
					return false;
				}
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "assert")) {
			if (!parseExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (parseExact(tokens1, ":")) {
				if (!parseExpression(tokens1)) {
					setErrorMessage(tokens.peek());
					return false;
				}
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "switch")) {
			if (!parseParExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
			while (parseSwitchBlockStatementGroup(tokens1)) {
				tokens.mergeBranch(tokens1);
				tokens1 = tokens.createBranch();
			}
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "while")) {
			if (!parseParExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseStatement(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "do")) {
			if (!parseStatement(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, "while")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseParExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, ";")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "for")) {
			if (!parseExact(tokens1, "(")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseForControl(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, ")")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseStatement(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "break")) {
			MyList tokens2 = tokens1.createBranch();
			if (parseIdentifier(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			if (!parseExact(tokens2, ";")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "continue")) {
			MyList tokens2 = tokens1.createBranch();
			if (parseIdentifier(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			if (!parseExact(tokens2, ";")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "return")) {
			MyList tokens2 = tokens1.createBranch();
			if (parseExpression(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			if (!parseExact(tokens2, ";")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "throw")) {
			if (!parseExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, ";")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "synchronized")) {
			if (!parseParExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseBlock(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "try")) {
			if (!parseBlock(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			MyList tokens2 = tokens1.createBranch();
			boolean error = true;
			if (parseCatches(tokens2)) {
				tokens1.mergeBranch(tokens2);
				error &= false;
			}
			tokens2 = tokens1.createBranch();
			if (parseFinally(tokens2)) {
				tokens1.mergeBranch(tokens2);
				error &= false;
			}
			if (error) {
				setErrorMessage(tokens.peek());
				return false;
			}

			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "try")) {
			if (!parseResourceSpecification(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseBlock(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			MyList tokens2 = tokens1.createBranch();
			if (parseCatches(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			tokens2 = tokens1.createBranch();
			if (parseFinally(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseStatementExpression(MyList tokens) {
		return parseExpression(tokens);
	}

	public static boolean parseCatches(MyList tokens) {
		if (!parseCatchClause(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1;
		do {
			tokens1 = tokens.createBranch();
			if (parseCatchClause(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else {
				break;
			}
		} while (true);

		return true;
	}

	public static boolean parseCatchClause(MyList tokens) {
		if (!parseExact(tokens, "catch")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, "(")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1;
		do {
			tokens1 = tokens.createBranch();
			if (parseVariableModifier(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else {
				break;
			}
		} while (true);
		if (!parseCatchType(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, ")")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseBlock(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseCatchType(MyList tokens) {
		do {
			if (!parseQualifiedIdentifier(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, "|"));
		return true;
	}

	public static boolean parseFinally(MyList tokens) {
		if (!parseExact(tokens, "finally")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseBlock(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseResourceSpecification(MyList tokens) {
		if (!parseExact(tokens, "(")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseResources(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		parseExact(tokens, ";");
		if (!parseExact(tokens, ")")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseResources(MyList tokens) {
		do {
			if (!parseResource(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ";"));
		return true;
	}

	public static boolean parseResource(MyList tokens) {
		MyList tokens1;
		do {
			tokens1 = tokens.createBranch();
			if (parseVariableModifier(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else {
				break;
			}
		} while (true);
		if (!parseReferenceType(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseVariableDeclaratorId(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, "=")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExpression(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseSwitchBlockStatementGroups(MyList tokens) {
		MyList tokens1;
		do {
			tokens1 = tokens.createBranch();
			if (parseSwitchBlockStatementGroup(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else {
				break;
			}
		} while (true);
		return true;
	}

	public static boolean parseSwitchBlockStatementGroup(MyList tokens) {
		if (!parseSwitchLabels(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseBlockStatements(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseSwitchLabels(MyList tokens) {
		if (!parseSwitchLabel(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}

		MyList tokens1;
		do {
			tokens1 = tokens.createBranch();
			if (parseSwitchLabel(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else {
				break;
			}
		} while (true);
		return true;
	}

	public static boolean parseSwitchLabel(MyList tokens) {
		if (parseExact(tokens, "case")) {
			MyList tokens1 = tokens.createBranch();
			MyList tokens2 = tokens.createBranch();
			if (parseExpression(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else if (parseEnumConstantName(tokens1)) {
				tokens.mergeBranch(tokens2);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens, ":")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			return true;
		}
		if (!parseExact(tokens, "default")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, ":")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseEnumConstantName(MyList tokens) {
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseForControl(MyList tokens) {
		MyList tokens1 = tokens.createBranch();

		if (parseForVarControl(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		if (!parseForInit(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, ";")) {

		}
		tokens1 = tokens.createBranch();
		if (parseExpression(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		if (!parseExact(tokens, ";")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens1 = tokens.createBranch();
		if (parseForUpdate(tokens)) {
			tokens.mergeBranch(tokens1);
		}
		return true;
	}

	public static boolean parseForVarControl(MyList tokens) {
		MyList tokens1;
		do {
			tokens1 = tokens.createBranch();
			if (parseVariableModifier(tokens1)) {
				tokens.mergeBranch(tokens1);
			} else {
				break;
			}
		} while (true);
		if (!parseType(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseVariableDeclaratorId(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseForVarControlRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseForVarControlRest(MyList tokens) {
		if (!parseForVariableDeclaratorsRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, ";")) {

		}
		MyList tokens1 = tokens.createBranch();
		if (parseExpression(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		if (!parseExact(tokens, ";")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens1 = tokens.createBranch();
		if (parseForUpdate(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		return true;
	}

	public static boolean parseForVariableDeclaratorsRest(MyList tokens) {
		if (parseExact(tokens, "=")) {
			if (!parseVariableInitializer(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			return true;
		}
		while (parseExact(tokens, ",")) {
			if (!parseVariableDeclarator(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		}
		return true;
	}

	public static boolean parseForInit(MyList tokens) {
		return parseForUpdate(tokens);
	}

	public static boolean parseForUpdate(MyList tokens) {
		do {
			if (!parseStatementExpression(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseExpression(MyList tokens) {
		if (!parseExpression1(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseAssignmentOperator(tokens1)) {
			if (!parseExpression1(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		return true;
	}

	public static boolean parseExpression1(MyList tokens) {
		if (!parseExpression2(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseExpression1Rest(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		return true;
	}

	public static boolean parseExpression1Rest(MyList tokens) {
		if (!parseExact(tokens, "?")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExpression(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, ":")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExpression1(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseExpression2(MyList tokens) {
		if (!parseExpression3(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.branch();
		if (parseExpression2Rest(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		return true;
	}

	public static boolean parseExpression2Rest(MyList tokens) {
		if (parseExact(tokens, "inctanceof")) {
			if (!parseType(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			return true;
		}
		MyList tokens1 = tokens.branch();
		while (parseInfixOp(tokens1)) {
			if (!parseExpression3(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			tokens1 = tokens.createBranch();
		}
		return true;
	}

	public static boolean parseExpression3(MyList tokens) {
		MyList tokens1 = tokens.branch();
		if (parsePrefixOp(tokens1)) {
			if (!parseExpression3(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.branch();
		if (parseExact(tokens1, "(")) {
			boolean isTypeCast = false;
			MyList tokens2 = tokens1.branch();
			MyList tokens3 = tokens1.branch();
			if (parseExpression(tokens2)) {
				tokens1.mergeBranch(tokens2);
			} else if (parseType(tokens3)) {
				isTypeCast = true;
				tokens1.mergeBranch(tokens3);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, ")")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens2 = tokens1.branch();
			if (parseExpression3(tokens2)) {
				tokens1.mergeBranch(tokens2);
			} else if (isTypeCast) {
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.branch();
		if (parsePrimary(tokens1)) {
			MyList tokens2 = tokens1.branch();
			while (parseSelector(tokens2)) {
				tokens1.mergeBranch(tokens2);
				tokens2 = tokens1.branch();
			}
			tokens2 = tokens1.branch();
			while (parsePostfixOp(tokens2)) {
				tokens1.mergeBranch(tokens2);
				tokens2 = tokens1.branch();
			}
			tokens.mergeBranch(tokens1);
			return true;
		}

		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parsePrimary(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseLiteral(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseParExpression(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "this")) {
			MyList tokens2 = tokens1.branch();
			if (parseArguments(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "super")) {
			if (!parseSuperSuffix(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "new")) {
			if (!parseCreator(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.createBranch();
		if (parseNonWildcardTypeArguments(tokens1)) {
			MyList tokens2 = tokens1.createBranch();
			MyList tokens3 = tokens1.createBranch();
			if (parseExplicitGenericInvocationSuffix(tokens2)) {
				tokens1.mergeBranch(tokens2);
			} else if (parseExact(tokens3, "this")) {
				if (!parseArguments(tokens3)) {
					setErrorMessage(tokens.peek());
					return false;
				}
				tokens1.mergeBranch(tokens3);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseQualifiedIdentifier(tokens1)) {
			MyList tokens2 = tokens1.branch();
			if (parseIdentifierSuffix(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseBasicType(tokens1)) {
			while (parseExact(tokens1, "[]")) {
			}
			if (!parseExact(tokens1, ".")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, "class")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "void")) {
			if (!parseExact(tokens1, ".")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, "class")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseLiteral(MyList tokens) {
		if (parseIntegerLiteral(tokens)) {
			return true;
		} else if (parseFloatingPointLiteral(tokens)) {
			return true;
		} else if (parseCharacterLiteral(tokens)) {
			return true;
		} else if (parseStringLiteral(tokens)) {
			return true;
		} else if (parseBooleanLiteral(tokens)) {
			return true;
		} else if (parseNullLiteral(tokens)) {
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseParExpression(MyList tokens) {
		if (!parseExact(tokens, "(")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExpression(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExact(tokens, ")")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseArguments(MyList tokens) {
		if (!parseExact(tokens, "(")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (parseExpression(tokens)) {
			while (parseExact(tokens, ",")) {
				if (!parseExpression(tokens)) {
					setErrorMessage(tokens.peek());
					return false;
				}
			}
		}

		if (!parseExact(tokens, ")")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseSuperSuffix(MyList tokens) {
		MyList tokens1 = tokens.branch();
		if (parseArguments(tokens)) {
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.branch();
		if (parseExact(tokens1, ".")) {
			if (!parseIdentifier(tokens1)) {
				MyList tokens2 = tokens1.branch();
				if (parseArguments(tokens2)) {
					tokens1.mergeBranch(tokens2);
				}
			}
			tokens.mergeBranch(tokens1);
			return true;
		}

		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseExplicitGenericInvocationSuffix(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "super")) {
			if (!parseSuperSuffix(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseIdentifier(tokens1)) {
			if (!parseArguments(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseCreator(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseNonWildcardTypeArguments(tokens1)) {
			if (!parseCreatedName(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseClassCreatorRest(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseCreatedName(tokens1)) {
			MyList tokens2 = tokens1.createBranch();
			MyList tokens3 = tokens1.createBranch();
			if (parseClassCreatorRest(tokens2)) {
				tokens1.mergeBranch(tokens2);
			} else if (parseArrayCreatorRest(tokens3)) {
				tokens.mergeBranch(tokens3);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseCreatedName(MyList tokens) {
		if (!parseType(tokens)) {
			return false;
		}
		MyList tokens1 = tokens.branch();
		if (parseTypeArgumentsOrDiamond(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		while (parseExact(tokens, ".")) {
			if (!parseIdentifier(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens1 = tokens.branch();
			if (parseTypeArgumentsOrDiamond(tokens1)) {
				tokens.mergeBranch(tokens1);
			}
		}
		return true;
	}

	public static boolean parseClassCreatorRest(MyList tokens) {
		if (!parseArguments(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseClassBody(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		return true;
	}

	public static boolean parseArrayCreatorRest(MyList tokens) {
		if (!parseExact(tokens, "[")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "]")) {
			while (parseExact(tokens1, "[]")) {
			}
			if (!parseArrayInitializer(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExpression(tokens1)) {
			if (!parseExact(tokens1, "]")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			while (parseExact(tokens1, "[")) {
				if (!parseExpression(tokens1)) {
					setErrorMessage(tokens.peek());
					return false;
				}
				if (!parseExact(tokens1, "]")) {
					setErrorMessage(tokens.peek());
					return false;
				}
			}
			while (parseExact(tokens1, "[]")) {
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseIdentifierSuffix(MyList tokens) {
		MyList tokens1 = tokens.branch();
		if (parseExact(tokens, "[")) {
			MyList tokens2 = tokens1.branch();
			MyList tokens3 = tokens1.branch();
			boolean foundDoubleSquare = false;
			while (parseExact(tokens2, "[]")) {
				foundDoubleSquare = true;
			}
			if (parseExact(tokens2, ".")) {
				if (!parseExact(tokens2, "class")) {
					setErrorMessage(tokens.peek());
					return false;
				}
				tokens1.mergeBranch(tokens2);
			} else if (!foundDoubleSquare && parseExpression(tokens3)) {
				tokens1.mergeBranch(tokens3);
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.branch();
		if (parseArguments(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}

		tokens1 = tokens.branch();
		if (parseExact(tokens1, ".")) {
			MyList tokens2 = tokens1.branch();
			MyList tokens3 = tokens1.branch();
			MyList tokens4 = tokens1.branch();
			MyList tokens5 = tokens1.branch();
			MyList tokens6 = tokens1.branch();
			if (parseExact(tokens2, "class")) {
				tokens1.mergeBranch(tokens2);
			} else if (parseExplicitGenericInvocation(tokens3)) {
				tokens1.mergeBranch(tokens3);
			} else if (parseExact(tokens4, "this")) {
				tokens1.mergeBranch(tokens4);
			} else if (parseExact(tokens5, "super")) {
				if (!parseArguments(tokens5)) {
					setErrorMessage(tokens.peek());
					return false;
				}
				tokens1.mergeBranch(tokens5);
			} else if (parseExact(tokens6, "new")) {
				MyList tokens7 = tokens6.createBranch();
				if (parseNonWildcardTypeArguments(tokens7)) {
					tokens6.mergeBranch(tokens7);
				}
				if (!parseInnerCreator(tokens6)) {
					setErrorMessage(tokens.peek());
					return false;
				}
				tokens1.mergeBranch(tokens6);
			} else {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseExplicitGenericInvocation(MyList tokens) {
		if (!parseNonWildcardTypeArguments(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		if (!parseExplicitGenericInvocationSuffix(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseInnerCreator(MyList tokens) {

		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.createBranch();
		if (parseNonWildcardTypeArgumentsOrDiamond(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		if (!parseClassCreatorRest(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseSelector(MyList tokens) {
		MyList tokens1 = tokens.createBranch();
		if (parseExact(tokens1, ".") && parseIdentifier(tokens1)) {
			MyList tokens2 = tokens1.branch();
			if (parseArguments(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, ".") && parseExplicitGenericInvocation(tokens1)) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, ".") && parseExact(tokens1, "this")) {
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, ".") && parseExact(tokens1, "super")) {
			if (!parseSuperSuffix(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, ".") && parseExact(tokens1, "new")) {
			MyList tokens2 = tokens1.branch();
			if (parseNonWildcardTypeArguments(tokens2)) {
				tokens1.mergeBranch(tokens2);
			}
			if (!parseInnerCreator(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		tokens1 = tokens.createBranch();
		if (parseExact(tokens1, "[")) {
			if (!parseExpression(tokens1)) {
				setErrorMessage(tokens.peek());
				return false;
			}
			if (!parseExact(tokens1, "]")) {
				setErrorMessage(tokens.peek());
				return false;
			}
			tokens.mergeBranch(tokens1);
			return true;
		}
		return false;
	}

	public static boolean parseEnumBody(MyList tokens) {
		if (!parseExact(tokens, "{")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.branch();
		if (parseEnumConstants(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		parseExact(tokens1, ",");
		tokens1 = tokens.branch();
		if (parseEnumBodyDeclarations(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		if (!parseExact(tokens1, "}")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		return true;
	}

	public static boolean parseEnumConstants(MyList tokens) {
		do {
			if (!parseEnumConstant(tokens)) {
				setErrorMessage(tokens.peek());
				return false;
			}
		} while (parseExact(tokens, ","));
		return true;
	}

	public static boolean parseEnumConstant(MyList tokens) {
		MyList tokens1 = tokens.branch();
		if (parseAnnotations(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		if (!parseIdentifier(tokens)) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens1 = tokens.createBranch();
		if (parseArguments(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		tokens1 = tokens.createBranch();
		if (parseClassBody(tokens1)) {
			tokens.mergeBranch(tokens1);
		}
		return true;
	}

	public static boolean parseEnumBodyDeclarations(MyList tokens) {
		if (!parseExact(tokens, ";")) {
			setErrorMessage(tokens.peek());
			return false;
		}
		MyList tokens1 = tokens.branch();
		while (parseClassBodyDeclaration(tokens)) {
			tokens.mergeBranch(tokens1);
		}
		return true;
	}

	public static boolean parseAnnotationTypeBody(MyList tokens) {
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseAnnotationTypeElementDeclarations(MyList tokens) {
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseAnnotationTypeElementDeclaration(MyList tokens) {
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseAnnotationTypeElementRest(MyList tokens) {
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseAnnotationMethodOrConstantRest(MyList tokens) {
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseAnnotationMethodRest(MyList tokens) {
		setErrorMessage(tokens.peek());
		return false;
	}

	public static boolean parseBasicType(MyList tokens) {
		List<String> basicTypes = Arrays.asList(new String[] { "byte", "short",
				"char", "int", "long", "float", "double", "boolean" });
		if (!basicTypes.contains(tokens.peek().getValue())) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseModifier(MyList tokens) {
		List<String> modifiers = Arrays.asList(new String[] { "Annotation",
				"public", "protected", "private", "static", "abstract",
				"final", "native", "synchronized", "transient", "volatile",
				"strictfp" });
		if (!modifiers.contains(tokens.peek().getValue())) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseAssignmentOperator(MyList tokens) {
		if (!tokens.peek().isAssignmentOperator()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseInfixOp(MyList tokens) {
		if (!tokens.peek().isInfixOperator()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parsePrefixOp(MyList tokens) {

		if (!tokens.peek().isPrefixOperator()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parsePostfixOp(MyList tokens) {
		if (!tokens.peek().isPostfixOperator()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseIntegerLiteral(MyList tokens) {
		if (!tokens.peek().isIntegerLiteral()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseFloatingPointLiteral(MyList tokens) {
		if (!tokens.peek().isFloatingPointLiteral()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseCharacterLiteral(MyList tokens) {
		if (!tokens.peek().isCharacterLiteral()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseStringLiteral(MyList tokens) {
		if (!tokens.peek().isStringLiteral()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseBooleanLiteral(MyList tokens) {
		if (!tokens.peek().isBooleanLiteral()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static boolean parseNullLiteral(MyList tokens) {
		if (!tokens.peek().isNullLiteral()) {
			setErrorMessage(tokens.peek());
			return false;
		}
		tokens.nextToken();
		return true;
	}

	public static MyList getTokensList() {
		return tokens;
	}

	public static boolean start(List<Token> tokensList) {
		tokens = new MyList(tokensList.size());
		for (int i = tokensList.size() - 1; i >= 0; i--) {
			tokens.add(tokensList.get(i));
		}
		return parseCompilationUnit(tokens);
	}

}
